import CommandBinder from "./CommandBinder"
import Engine from "./Engine"
import MarketContext from "./MarketContext"
import MessageBus from "./message/MessageBus"
import Module from "./module/Module"
export interface fetchedItem {
  moduleName: string
  isModule: boolean
  startAwait: number
  finishAwait: number
}
export default class EngineContext {
  market: MarketContext
  fetchedModules: fetchedItem[]
  engine: Engine
  messageBus: MessageBus
  commandBinder: CommandBinder
  getModuleSync: Engine["getModuleSync"]
  addComponent: Engine["addComponent"]
  getComponentByType: Engine["getComponentByType"]
  getComponents: Engine["getComponents"]
  removeComponent: Engine["removeComponent"]
  subscribe: Engine["subscribe"]
  unsubscribe: Engine["unsubscribe"]
  broadcast: Engine["broadcast"]
  claimRenderLayer: Engine["claimRenderLayer"]
  getRenderLayer: Engine["getRenderLayer"]
  disposeRenderLayer: Engine["disposeRenderLayer"]
  startGenerator: Engine["startGenerator"]
  stopGenerator: Engine["stopGenerator"]
  after: Engine["after"]
  deactivate: Engine["deactivate"]
  toggleRendering: Engine["toggleRendering"]
  getXrFrame: Engine["getXrFrame"]
  constructor(e: Engine) {
    this.fetchedModules = []
    this.engine = e
    this.messageBus = e.msgBus
    this.market = new MarketContext(e.market)
    this.commandBinder = e.commandBinder
    this.getModuleSync = e.getModuleSync.bind(e)
    this.addComponent = e.addComponent.bind(e)
    this.getComponentByType = e.getComponentByType.bind(e)
    this.getComponents = e.getComponents.bind(e)
    this.removeComponent = e.removeComponent.bind(e)
    this.subscribe = e.subscribe.bind(e)
    this.unsubscribe = e.unsubscribe.bind(e)
    this.broadcast = e.broadcast.bind(e)
    this.claimRenderLayer = e.claimRenderLayer.bind(e)
    this.getRenderLayer = e.getRenderLayer.bind(e)
    this.disposeRenderLayer = e.disposeRenderLayer.bind(e)
    this.startGenerator = e.startGenerator.bind(e)
    this.stopGenerator = e.stopGenerator.bind(e)
    this.after = e.after.bind(e)
    this.deactivate = e.deactivate.bind(e)
    this.toggleRendering = e.toggleRendering.bind(e)
    this.getXrFrame = e.getXrFrame.bind(e)
  }
  async getModule<A extends typeof Module = typeof Module>(e: A) {
    const startAwait = Date.now()
    const module = await this.engine.getModule<A>(e)
    const finishAwait = Date.now()
    this.fetchedModules.push({
      moduleName: module.name,
      isModule: !0,
      startAwait,
      finishAwait
    })
    return module
  }
  async getModuleBySymbol<B extends Module = Module>(e: symbol) {
    const startAwait = Date.now()
    const module = await this.engine.getModuleBySymbol<B>(e)
    const finishAwait = Date.now()
    this.fetchedModules.push({
      moduleName: module.name,
      isModule: !0,
      startAwait,
      finishAwait
    })
    return module
  }
  getLoadedDependencies() {
    return [...this.fetchedModules, ...this.market.getLoadedDependencies()]
  }
  get msgBus() {
    return this.messageBus
  }
}
